import {isUrl} from '@v-c/utils'
import { omit } from 'lodash'
import type { RouteRecordRaw } from 'vue-router'
import type { MenuData, MenuDataItem } from '@/layout/basic-layout/typing'
import { ROOT_ROUTE_REDIRECT_PATH } from '@/router/constant'

let cache_key = 1

const getCacheKey = () => `Cache_Key_${cache_key++}`

/**
 * 格式化菜单
 * @param route
 * @param path
 */
function formatMenu(route: RouteRecordRaw, path?: string) {
  return {
    id: route.meta?.id,
    parentId: route.meta?.parentId,
    title: route.meta?.title || '',
    icon: route.meta?.icon || '',
    path: path ?? route.path,
    hideInMenu: route.meta?.hideInMenu || false,
    parentKeys: route.meta?.parentKeys || [],
    hideInBreadcrumb: route.meta?.hideInBreadcrumb || false,
    hideChildrenInMenu: route.meta?.hideChildrenInMenu || false,
    locale: route.meta?.locale,
    keepAlive: route.meta?.keepAlive || false,
    name: route.name as string,
    url: route.meta?.url || '',
    target: route.meta?.target || '_blank',
  }
}


export function genRoutes(routes: RouteRecordRaw[], parent?: MenuDataItem) {
  const menuData: MenuData = []
  routes.forEach((route) => {
    let path = route.path
    if (!path.startsWith('/') && !isUrl(path)) {
      // 判断当前是不是以 /开头，如果不是就表示当前的路由地址为不完全的地址
      if (parent)
        path = `${parent.path}/${path}`
      else
        path = `/${path}`
    }
    // 判断是不是存在name，如果不存在name的情况下，自动补充一个自定义的name，为了更容易的去实现保活的功能，name是必须的
    if (!route.name)
      route.name = getCacheKey()
    const item: MenuDataItem = formatMenu(route, path)
    item.children = []
    if (route.children && route.children.length)
      item.children = genRoutes(route.children, item)
    if (item.children?.length === 0)
      delete item.children
    menuData.push(item)
  })
  return menuData
}

/**
 * 根据菜单数据生成树形路由和菜单结构
 * @param menus 菜单数据数组，包含各个菜单项的信息
 * @returns 返回一个对象，包含菜单数据和路由数据
 *
 * 该函数首先遍历菜单数据，为每个菜单项创建一个对应的路由记录和格式化后的菜单项
 * 然后根据菜单项之间的父子关系，构建树形结构的路由和菜单数据
 * 最后返回构建好的菜单数据和路由数据
 */
export function generateTreeRoutes(menus: MenuData) {
  console.log('generateTreeRoutes menus', menus)
  // 创建一个映射，用于存储菜单项ID和对应的路由记录
  const routeDataMap = new Map<string | number, RouteRecordRaw>()
  // 创建一个映射，用于存储菜单项ID和对应的格式化后的菜单项
  const menuDataMap = new Map<string | number, MenuDataItem>()
  // 遍历菜单数据，创建路由记录和格式化菜单项
  for (const menuItem of menus) {
    if (!menuItem.id)
      continue
    console.log('generateTreeRoutes menuItem', menuItem)
    // 根据菜单项信息创建路由记录
    const route = {
      path: menuItem.path,
      name: menuItem.name || getCacheKey(),
      component: getRouterModule(menuItem.url!),
      redirect: menuItem.redirect || undefined,
      meta: {
        title: menuItem?.menuName as string,
        icon: menuItem?.icon as string,
        keepAlive: menuItem?.keepAlive,
        id: menuItem?.id,
        parentId: menuItem?.parentId,
        affix: menuItem?.affix,
        parentKeys: menuItem?.parentKeys,
        url: menuItem?.url,
        hideInMenu: menuItem?.hideInMenu,
        hideChildrenInMenu: menuItem?.hideChildrenInMenu,
        hideInBreadcrumb: menuItem?.hideInBreadcrumb,
        target: menuItem?.target,
        locale: menuItem?.locale,
      },
    } as RouteRecordRaw
    // 格式化菜单项
    const menu = formatMenu(route)
    // 将路由记录和格式化后的菜单项分别存入对应的映射中
    routeDataMap.set(menuItem.id, route)
    menuDataMap.set(menuItem.id, menu)
  }

  // 初始化路由数据和菜单数据数组
  const routeData: RouteRecordRaw[] = []
  const menuData: MenuData = []

  // 再次遍历菜单数据，根据父子关系构建树形结构
  for (const menuItem of menus) {
    if (!menuItem.id)
      continue
    // 获取当前菜单项对应的路由记录和格式化后的菜单项
    const currentRoute = routeDataMap.get(menuItem.id)
    const currentItem = menuDataMap.get(menuItem.id)
    if (!menuItem.parentId) {
      if (currentRoute && currentItem) {
        routeData.push(currentRoute)
        menuData.push(currentItem)
      }
    }
    else {
      // 如果当前菜单项有父菜单，则找到父菜单项并将其作为子菜单或路由
      const pRoute = routeDataMap.get(menuItem.parentId)
      const pItem = menuDataMap.get(menuItem.parentId)
      if (currentItem && currentRoute && pRoute && pItem) {
        if (pRoute.children && pItem.children) {
          pRoute.children.push(currentRoute)
          pItem.children.push(currentItem)
        }
        else {
          pItem.children = [currentItem]
          pRoute.children = [currentRoute]
        }
      }
    }
  }
  // 返回构建好的菜单数据和路由数据
  return {
    menuData,
    routeData,
  }
}

function checkComponent(component: RouteRecordRaw['component']) {
  for (const componentKey in basicRouteMap) {
    if (component === (basicRouteMap as any)[componentKey])
      return undefined
  }
  return component
}

// 路由拉平处理
function flatRoutes(routes: RouteRecordRaw[], parentName?: string, parentComps: RouteRecordRaw['component'][] = []) {
  const flatRouteData: RouteRecordRaw[] = []
  for (const route of routes) {
    const parentComponents = [...parentComps]
    const currentRoute = omit(route, ['children']) as RouteRecordRaw
    if (!currentRoute.meta)
      currentRoute.meta = {}
    if (parentName)
      currentRoute.meta.parentName = parentName
    if (parentComponents.length > 0)
      currentRoute.meta.parentComps = parentComponents
    currentRoute.meta.originPath = currentRoute.path
    flatRouteData.push(currentRoute)
    if (route.children && route.children.length) {
      const comp = checkComponent(route.component)
      if (comp)
        parentComponents.push(comp)
      flatRouteData.push(...flatRoutes(route.children, route.name as string, [...parentComponents]))
    }
  }
  return flatRouteData
}

export function generateFlatRoutes(routes: RouteRecordRaw[]) {
  const flatRoutesList = flatRoutes(routes)
  // 拿到拉平后的路由，然后统一添加一个父级的路由,通过这层路由实现保活的功能
  const parentRoute: RouteRecordRaw = {
    path: '/',
    redirect: ROOT_ROUTE_REDIRECT_PATH,
    name: 'ROOT_EMPTY_PATH',
    // fix: https://github.com/antdv-pro/antdv-pro/issues/179
    // component: getRouterModule('RouteView'),
    children: flatRoutesList,
  }
  return [parentRoute]
}


export function getRouterModule(path?: string): any {
  if (!path)
    return basicRouteMap.ComponentError
  // 判断是否在basicRouteMap中存在
  if (path in basicRouteMap)
    return (basicRouteMap as any)[path]

  // 判断开头是不是/
  if (path.startsWith('/'))
    path = path.slice(1)
  // 组装数据格式
  const fullPath = `/src/views/${path}.vue`
  const fullPathIndex = `/src/views/${path}/index.vue`
  if (fullPathIndex in routerModules)
    return checkEager(routerModules[fullPathIndex])


  console.log('getRouterModule fullPath', fullPath)
  // 返回插件信息
  return checkEager(routerModules[fullPath])
}

function checkEager(module: any) {
  if (typeof module === 'object' && 'default' in module)
    return module.default

  return module
}

export const basicRouteMap = {
  // iframe模式下使用
  Iframe: () => import('@/views/common/iframe.vue'),
  // 一般用于存在子集的页面
  RouteView: () => import('@/layout/modules/route-view.vue'),
  // 空页面
  ComponentError: () => import('@/views/exception/404.vue'),
}

const routerModules = import.meta.glob([
  '@/views/**/*.vue',
])
